Ext.define('ArvoreKD.controller.Arvores', {
	extend: 'Ext.app.Controller',
	
	stores: [
		'Nos'
	],
	
	models: [
		'No'
	],
	
	views: [],
	
	init: function() {
		var me = this; 
		
		me.control({
			'viewport': {
				render: me.inicializarArvore
			},
			
			'button[action="inserir"]': {
				click: me.inserir
			},
			
			'numberfield[name="coord-x"]': {
				render: me.inicializarX,
				specialkey: me.teclas,
				keypress: me.trocarField
			},
			
			'numberfield[name="coord-y"]': {
				specialkey: me.inicializarY,
				keypress: me.trocarField
			}
		});
	},
	
	maiorNivel: 0,
	canvasDom: null,
	
	inicializarArvore: function() {
		try {
			KDFacade.removerArvore({
				callback: function(resposta) {
					
				},
				errorHandler: function(mensagem, erro) {
					alert("Falha ao chamar removerArvore: " + mensagem);
				},
				async: false
			});
		} catch(e) {
			alert("Falha na funcao inicializarArvore: " + e.message);
		}
	},
	
	inicializarX: function(field, e) {
		try {
			field.focus(true, true);
		} catch(e) {
			alert("Falha na funcao inicializarX: " + e.message);
		}
	},
	
	inicializarY: function(field, e) {
		try {
			if(e.getKey() == e.ENTER) {
				field.up('fieldcontainer').down('button').focus(true, true);
			}
		} catch(e) {
			alert("Falha na funcao inicializarY: " + e.message);
		}
	},
	
	teclas: function(field, e) {
		try {
			if(e.getKey() == e.ENTER) {
				field.up('fieldcontainer').down('numberfield[name="coord-y"]').focus(true, true);
			}
		} catch(e) {
			alert("Falha na funcao teclas: " + e.message);
		}
	},
	
	trocarField: function(field, e) {
		try {
			if (field.getName() == 'coord-x') {
				field.up('form').down('numberfield[name="coord-y"]').focus(true, true);
			}
			
			if (field.getName() == 'coord-y') {
				field.up('form').down('button').focus(true, true);
			}
		} catch(e) {
			alert("Falha na funcao trocarField: " + e.message);
		}
	},
	
	inserir: function(button, e) {
		try {
			var me = this,
				container = button.up('fieldcontainer');
				x = container.down('numberfield[name="coord-x"]').getValue(),
				y = container.down('numberfield[name="coord-y"]').getValue(),
				form = container.up('form'),
				panel = form.up('panel');
				
			if(!form.getForm().isValid()) {
				button.up('fieldcontainer').down('numberfield[name="coord-x"]').focus(true, true);
				return false;
			}
			
			if(!me.canvasDom) {
				me.canvas(form.up('viewport').down('panel[region="east"]'));
			}
			
			me.inserirNo(x, y, panel);
			button.up('fieldcontainer').down('numberfield[name="coord-x"]').focus(true, true);
		} catch(e) {
			alert("Falha na funcao inserir: " + e.message);
		}
	},
	
	inserirNo: function(x, y, panel) {
		try {
			var me = this;
			
			KDFacade.inserir(x, y, {
				callback: function(no) {
					me.estruturar(no.nivel);
					me.buscar(panel);
					me.atualizarCanvas(no);
				},
				errorHandler: function(mensagem, erro) {
					alert("Falha na funcao inserir em inserirNo: " + mensagem);
				}
			});
		} catch(e) {
			alert("Falha na funcao inserirNo: " + e.message);
		}
	},
	
	estruturar: function(nivel) {
		try {
			var me = this;
				
			if(me.maiorNivel == 0 || nivel > me.maiorNivel) {
				me.maiorNivel = nivel;
				
				var quantidadePaineis = 0,
					panelLayout = null;
				
				while(quantidadePaineis < Math.pow(2,nivel)) {
					quantidadePaineis++;
					
					if (quantidadePaineis == 1) {
						panelLayout = panel.add({
							id: 'panel-nivel' + nivel,
							xtype: 'panel',
							border: false,
							layout: {
		                        type: 'hbox'
		                    },
							defaults: {
								flex: 100/Math.pow(2,nivel),
								align: 'middle'
							}
						});
					}
					
					panelLayout.add({
						xtype: 'panel',
						border: false,
						frame: false,
						style: {
							paddingTop: '5px'
					    }
					});
				}						
			}
		} catch(e) {
			alert("Falha na funcao estruturar: " + e.message);
		}
	},
	
	buscar: function() {
		try {
			KDFacade.buscar({
				callback: function(nos) {
					panel.items.each(function(pLayout, indexLayout, length) {
						if (Ext.getClass(pLayout) == Ext.panel.Panel) {
							pLayout.items.each(function(item, index, length) {
								if(nos[indexLayout-1] && nos[indexLayout-1][index]) {
									item.addCls('no');
									item.update(nos[indexLayout-1][index].representacao);
								}
							});
						}
					});
				},
				errorHandler: function(mensagem, erro) {
					alert("Falha na funcao buscar em inserirNo: " + mensagem);
				}
			});
		} catch(e) {
			alert("Falha na funcao buscar: " + e.message);
		}
	},
	
	atualizarCanvas: function(no) {
		try {
			var me = this,
				canvas = me.canvasDom,
				escala = 25,
				context = canvas.getContext("2d"),
				pontoZero = me.pontoZero(canvas);
				
			if(no.nivel%2 == 0) {
				context.beginPath();
				
				var yMenor = me.yLimite;
				var yMaior = me.yLimite;
				
				if(me.yUtilizados.length > 0) {
					me.yUtilizados.sort();
					yMenor = me.yUtilizados[0];
					yMaior = me.yUtilizados[me.yUtilizados.length-1];
				}
				
				if(pontoZero.y-(no.y*escala) < yMaior) {
					context.moveTo(pontoZero.x+(no.x*escala),me.yLimite);
					context.lineTo(pontoZero.x+(no.x*escala),yMaior);
					context.stroke();
				}
				
				if(pontoZero.y-(no.y*escala) > yMenor) {
					context.moveTo(pontoZero.x+(no.x*escala),pontoZero.y);
					context.lineTo(pontoZero.x+(no.x*escala),yMenor);
					context.stroke();
				}
				
				me.xUtilizados.push(pontoZero.x+(no.x*escala));
			} else {
				context.beginPath();
				
				me.xUtilizados.sort();
				var xMenor = me.xUtilizados[0];
				var xMaior = me.xUtilizados[me.xUtilizados.length-1];
				
				if(pontoZero.x+(no.x*escala) > xMaior) {
					context.moveTo(me.xLimite,pontoZero.y-(no.y*escala));
					context.lineTo(xMaior,pontoZero.y-(no.y*escala));
					context.stroke();
				}
				
				if(pontoZero.x+(no.x*escala) <= xMenor) {
					context.moveTo(pontoZero.x,pontoZero.y-(no.y*escala));
					context.lineTo(xMenor,pontoZero.y-(no.y*escala));
					context.stroke();
				}
				
				me.yUtilizados.push(pontoZero.y-(no.y*escala));
			}
		} catch(e) {
			alert("Falha na funcao atualizarCanvas: " + e.message);
		}
	},
	
	canvas: function(panel) {
		try {
			var me = this,
				titulo = 26,
				widthCanvas = panel.getWidth(),
				heightCanvas = panel.getHeight()-titulo;
				
			var canvasPanel = panel.add({
				xtype: 'box',
				autoEl: {
					tag: 'canvas',
					width: widthCanvas,
					height: heightCanvas
				}
			});
			
			var canvas = canvasPanel.el.dom;
			
			me.canvasDom = canvas;
			me.abcissas(canvas);
			me.ordenadas(canvas);
		} catch(e) {
			alert("Falha na funcao canvas: " + e.message);
		}
	},
	
	xLimite: null,
	yLimite: null,
	xUtilizados: [],
	yUtilizados: [],
	
	pontoZero: function(canvas) {
		try {
			var me = this,
				context = canvas.getContext("2d"),
				pontoZero = {x:canvas.width/4, y:canvas.height-(canvas.height/4)};
			
			context.moveTo(pontoZero.x,pontoZero.y);
			
			return pontoZero;
		} catch(e) {
			alert("Falha na funcao pontoZero: " + e.message);
		}
	},
	
	abcissas: function(canvas) {
		try {
			var me = this,
				context = canvas.getContext("2d"),
				pontoZero = me.pontoZero(canvas),
				xFinal = canvas.width-(pontoZero.x),
				yFinal = pontoZero.y;
			
			me.xLimite = xFinal;
			
			context.fillStyle = "black";
			
			context.lineTo(xFinal,yFinal);
			context.stroke();
			
			context.beginPath();
			context.moveTo(xFinal,yFinal-5);
			context.lineTo(xFinal,yFinal+5);
			context.lineTo(xFinal+10,yFinal);
			context.fill();
		} catch(e) {
			alert("Falha na funcao abcissas: " + e.message);
		}
	},
	
	ordenadas: function(canvas) {
		try {
			var me = this,
				context = canvas.getContext("2d"),
				pontoZero = me.pontoZero(canvas),
				xFinal = pontoZero.x,
				yFinal = canvas.height-pontoZero.y;
				
			me.yLimite = yFinal;
				
			context.fillStyle = "black";
			
			context.lineTo(xFinal,yFinal);
			context.stroke();
			
			context.beginPath();
			context.moveTo(xFinal-5,yFinal);
			context.lineTo(xFinal+5,yFinal);
			context.lineTo(xFinal,yFinal-10);
			context.fill();
		} catch(e) {
			alert("Falha na funcao ordenadas: " + e.message);
		}
	}
});